home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / filtr21s.zip / FILTER21.C < prev    next >
C/C++ Source or Header  |  1994-06-08  |  9KB  |  328 lines

  1. /*  `filter', v. 2.1    Latest mod: 12:30 Jun 8 1994
  2.      A `grep'-like text searcher for multiple simultaneous keyword tests
  3.  
  4. Copyright 1994 by Joel Polowin, Department of Chemistry, Queen's University, 
  5. Kingston, Ontario, Canada.  Permission granted for free use and distribution;
  6. I want credit/blame for writing it.  E-mail: polowin@silicon.chem.queensu.ca,
  7. polowinj@qucdn.queensu.ca, Joel.Polowin@p4.f107.n249.z1.fidonet.org .
  8.  
  9. If you see something wrong with it or it fails to work, PLEASE let me know!
  10. */
  11.  
  12. #define LENGTH 601 /* 1 more than max # characters */
  13. #define ARGS 2000
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18. #include <string.h>
  19.  
  20. void syntax ()
  21. {
  22.    fprintf(stderr,"Syntax: filter [filename] [filename ...] string [string ...]\n  where");
  23.    fprintf(stderr," each string (max. of %d) is a term to be searched for",ARGS);
  24.    fprintf(stderr," in lines (max.\n  %d chars) in file",LENGTH-1);
  25.    fprintf(stderr," `filename', prefixed by one of the following characters:\n");
  26.    fprintf(stderr,"    +  to show lines which contain string\n");
  27.    fprintf(stderr,"    -  to show lines which do not contain string\n");
  28.    fprintf(stderr,"    =  to show lines which contain string, case sensitive\n");
  29.    fprintf(stderr,"    _  (underscore) to show lines which do not contain string,\n");
  30.    fprintf(stderr,"            case sensitive\n\n");
  31.    fprintf(stderr,"A string as above may be further prefixed with the letter 'o' to\n");
  32.    fprintf(stderr,"  print the line if the current OR the preceding condition is true.");
  33.    fprintf(stderr,"\nA string including blanks and the prefix may be enclosed in");
  34.    fprintf(stderr," double quotes.\nStrings beginning with one of `$&^' designate"); 
  35.    fprintf(stderr," file expansion; see filter21.doc.\n\nExamples:\n  filter armorial");
  36.    fprintf(stderr," =Vert +argent -gules _Or -azure -purpur +foil > tempfile.txt\n");
  37.    fprintf(stderr,"  type temp1.txt | filter +aardvark \042o+winged pig\042 ");
  38.    fprintf(stderr,"o+wombat \042_|B|\042\n\nFilter utility v.2.1 (C) 1994 by Joel");
  39.    fprintf(stderr," Polowin, Chem. Dept., Queen's University,\nKingston.  Permission");
  40.    fprintf(stderr," granted for free use; I want credit/blame for writing it.\n");
  41.    fprintf(stderr,"polowin@silicon.chem.queensu.ca, polowinj@qucdn.queensu.ca\n");
  42.    exit(1);
  43. }
  44.  
  45. void main(argc,argv)
  46. int argc;
  47. char *argv[];
  48. {
  49.    char line[LENGTH],lowline[LENGTH];
  50.    FILE *infile;
  51.    int  i,j,k,l,test,firststring,nostring,lowcase;
  52.    void syntax();
  53.    void strlow();
  54.    char flag[ARGS+1],orflag[ARGS+1];
  55.    char *myargv[ARGS+1];
  56.    int  blocksize;
  57.    char *prefix,*filename;
  58.  
  59.    firststring=0;
  60.    for(i=1; i<argc; i++)
  61.       {
  62.       if(*argv[i]=='=' || *argv[i]=='+' || *argv[i]=='-' || *argv[i]=='_')
  63.     {
  64.     test=*argv[i];
  65.     for(j=1; test==*(argv[i]+j); j++)
  66.        ;
  67.     if(j%2 && firststring==0) 
  68.        firststring=i;
  69.     argv[i]+=j/2;
  70.     }
  71.       }
  72.  
  73.    if(firststring==0)
  74.       {
  75.       fprintf(stderr,"Must specify a search string.\n");
  76.       syntax();
  77.       }
  78.  
  79.    nostring=argc-firststring;
  80.    if(nostring>ARGS)
  81.       {
  82.       fprintf(stderr,"Too many search strings specified.\n");
  83.       syntax();
  84.       }
  85.  
  86.    lowcase=0;
  87.    
  88.    for (i=0; i<ARGS+1; i++) orflag[i]=0;
  89.  
  90.    blocksize=0;
  91.    for (i=firststring; i<argc; i++) blocksize+=strlen(argv[i])+1;
  92.    if (NULL==(myargv[1]=malloc(blocksize)))
  93.       {
  94.       fprintf(stderr,"Can't allocate memory for string storage.\n");
  95.       exit(1);
  96.       }
  97.    strcpy(myargv[1],argv[firststring]);
  98.  
  99.    for(i=2; i<=nostring; i++)
  100.       {
  101.       myargv[i]=myargv[i-1]+strlen(myargv[i-1])+1;
  102.       strcpy(myargv[i],argv[i+firststring-1]);
  103.       }
  104.  
  105.    for (i=1; i<=nostring; i++)
  106.    {
  107.       j=0;
  108.       switch(*myargv[i])
  109.       {
  110.     case '+':
  111.        strlow(myargv[i]);
  112.        lowcase=1;
  113.     case '=':
  114.        flag[i]=1;
  115.        break;
  116.     case '-':
  117.        strlow(myargv[i]);
  118.        lowcase=1;
  119.     case '_':
  120.        flag[i]=0;
  121.        break;
  122.     case 'O':
  123.     case 'o':
  124.        orflag[i-1]=1;
  125.        myargv[i]++;
  126.        i--;
  127.        j=1;
  128.        break;
  129.     default:
  130.        fprintf(stderr,"Error in string no. %d: %s\n",i-1,myargv[i]);
  131.        syntax();
  132.       }
  133.  
  134.    if((!j) && (((test=*(myargv[i]+1))=='$') || (test=='&') || (test=='^')))
  135.       {
  136.       for(j=1; test==*(myargv[i]+1+j); j++)
  137.       ;  /* count identical flag chars */
  138.  
  139.       l=j/2;
  140.  
  141.       for (k=0; *(myargv[i]+k)!='\0'; k++)   /* shift string to delete */
  142.     *(myargv[i]+k+1)=*(myargv[i]+k+l+1);  /* half of flag chars */
  143.  
  144.       if(j%2) /* an odd number of flag chars: expand file */
  145.     {
  146.     if(test=='^') 
  147.        {
  148.        prefix="";
  149.        orflag[i-1]=0;
  150.        }
  151.     else
  152.        {
  153.        switch(*myargv[i])   /* determine prefix for expanded terms */
  154.           {                 /* from current prefix and expansion type */
  155.           case '+':
  156.          if(test=='$') prefix="o+";
  157.          else prefix="+";
  158.          break;
  159.           case '=':
  160.          if(test=='$') prefix="o=";
  161.          else prefix="=";
  162.          break;
  163.           case '-':
  164.          if(test=='$') prefix="-";
  165.          else prefix="o-";
  166.          break;
  167.           case '_':
  168.          if(test=='$') prefix="_";
  169.          else prefix="o_";
  170.          break;
  171.           default:
  172.          fprintf(stderr,"Bugger-up in program!\n");
  173.          exit(1);
  174.           }
  175.        }
  176.  
  177.     filename=myargv[i]+2;
  178.  
  179.     if(!(infile=fopen(filename,"r")))
  180.        {
  181.        fprintf(stderr,"Can't open search-term file %s\n",filename);
  182.        exit(1);
  183.        }
  184.  
  185.     if(test!='^') test=*myargv[i];  /* prefix of current term */
  186.  
  187.     blocksize=0;  /* figure out how much memory to allocate */
  188.     for(j=0;;j++)   /* for new terms */
  189.        {
  190.        if(NULL==fgets(line,LENGTH,infile)) break;
  191.        if(LENGTH==strlen(line)+1) fprintf(stderr,
  192.          "* Warning: truncated search term file %s line\n%s\n",
  193.          filename,line);
  194.        if(line[strlen(line)-1]=='\n') line[strlen(line)-1]='\0';
  195.        blocksize+=strlen(line)+1;
  196.        }
  197.  
  198.     if (j==0)
  199.        {
  200.        fprintf(stderr,"* Warning: empty search term file %s\n",
  201.           filename);
  202.        j=1;
  203.        }
  204.  
  205.     blocksize+=j*strlen(prefix);
  206.     rewind(infile);
  207.  
  208.     if(nostring+j-1>ARGS)
  209.        {
  210.        fprintf(stderr,"File expansion gives too many terms (%d max)\n",
  211.           ARGS);
  212.        exit(1);
  213.        }
  214.  
  215.     for(k=nostring; k>i; k--)      /* shift old myargv to make room */
  216.        myargv[k+j-1]=myargv[k];
  217.  
  218.     if(NULL==(myargv[i]=malloc(blocksize)))
  219.        {
  220.        fprintf(stderr,"Can't allocate memory for search term expansion.\n");
  221.        exit(1);
  222.        }
  223.  
  224.     for(k=0;k<j;k++)
  225.        {
  226.        fgets(line,LENGTH,infile);
  227.        if(line[strlen(line)-1]=='\n') line[strlen(line)-1]='\0';
  228.        if(k==0)
  229.           {
  230.           if(test=='^') strcpy(myargv[i],line);
  231.           else
  232.          {
  233.          *myargv[i]=test;
  234.          strcpy(myargv[i]+1,line);
  235.          }
  236.           }
  237.        else
  238.           {
  239.           myargv[i+k]=myargv[i+k-1]+strlen(myargv[i+k-1])+1;
  240.           strcpy(myargv[i+k],prefix);
  241.           strcat(myargv[i+k],line);
  242.           }
  243.        }
  244.  
  245.     fclose(infile);
  246.     nostring+=j-1;
  247.     i--;
  248.     }
  249.       }
  250.    }
  251.  
  252.    k=0;
  253.    do
  254.       {
  255.       k++;
  256.       if(firststring==1) infile=stdin;
  257.       else
  258.     if(!(infile=fopen(argv[k],"r")))
  259.        {
  260.        fprintf(stderr,"Can't open file %s for reading.\n",argv[k]);
  261.        syntax();
  262.        }
  263.       l=0;
  264.  
  265.       for (;;)
  266.     {
  267.     if(NULL==fgets(line,LENGTH,infile)) break;
  268.     if(LENGTH==strlen(line)+1) fprintf(stderr,"* Warning: truncated line \n%s\n",line);
  269.     if(lowcase) strlow(strcpy(lowline,line));
  270.     for(i=1; i<=nostring; i++)
  271.        {
  272.        test=0;
  273.        switch(*myargv[i])
  274.           {
  275.           case '=':
  276.           case '_':
  277.          if(NULL!=strstr(line,(myargv[i]+1))) test=1;
  278.          break;
  279.           default:
  280.          if(NULL!=strstr(lowline,(myargv[i]+1))) test=1;
  281.          break;
  282.           }
  283.        if(test!=flag[i] && orflag[i]==0) break;
  284.        if(test==flag[i])
  285.           while(orflag[i]==1) i++;
  286.        }
  287.     if(i>nostring)
  288.        {
  289.        if(firststring>2 && l==0)
  290.           {
  291.           printf("File %s:\n",argv[k]);
  292.           l=1;
  293.           }
  294.        printf("%s",line);
  295.        }
  296.     }
  297.       if(infile!=stdin) fclose(infile);
  298.       }
  299.    while(k<firststring-1);
  300.    exit(0);
  301. }
  302.  
  303. void strlow(string)
  304. char *string;
  305. {
  306.    while (*string!='\0')
  307.    {
  308.       *string=tolower(*string);
  309.       string++;
  310.    }
  311. }
  312.  
  313.  
  314. /*  Revision history:
  315.  
  316. Version 1.0 September 1992.
  317.  
  318. 1.1